package com.example.demo.controller;

import com.example.demo.common.*;
import com.example.demo.entity.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.parameters.P;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.soap.SAAJMetaFactory;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentHashMap;

import  static com.example.demo.common.ApplicationVariable.*;
import static com.example.demo.common.ApplicationVariable.SESSION_KEY_CHECK_CODE;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private CheckCodeTools codeTools;

    @Autowired
    private TimerTools timerTools;

    @Autowired
    private blacklist blacklist;

//    @RequestMapping("/reg")
//    public AjaxResult reg(UserInfo userInfo){
//        //后端开发永远不要相信前端
//
//        //1.进行非空判断
//        if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) || !StringUtils.hasLength(userInfo.getPassword()))
//            return AjaxResult.fail(-1,"参数有误");
//        //StringUtils.hasLength(userInfo.getUsername())即判断是否为空 包括""和null
//
//        //将密码进行加盐加密
//        userInfo.setPassword(PasswordTools.encrypt(userInfo.getPassword()));
//        //2.调用UserService执行添加方法，并将得到的结果添加到AjaxResult.data进行返回
//        int result = userService.reg(userInfo);
//        return AjaxResult.success(result);
//    }


//    @RequestMapping("/login")
//    public AjaxResult login(String username, String password, HttpServletRequest httpServletRequest){
//        if (!StringUtils.hasLength(username)||
//                !StringUtils.hasLength(password))
//            return AjaxResult.fail(-1,"参数有误");
//        UserInfo userInfo = userService.login(username);
//        if (userInfo == null&& userInfo.getId()<=0){
//            return AjaxResult.fail(-2,"用户名或密码输入错误");
//        }
//
//        if (!PasswordTools.decrypt(password,userInfo.getPassword())){
//            return AjaxResult.fail(-2,"用户名或密码输入错误");
//        }
//        //将当前成功登录的用户信息存储到session
//        HttpSession session =  httpServletRequest.getSession();
//        session.setAttribute(ApplicationVariable.SESSION_KEY_USERINFO,userInfo);
//
//        return AjaxResult.success(1);
//    }

    //// 用于存储 ip 地址和设定的拉黑时间十分钟
    public static final Map<String,Long> BLACKLIST_MAP = new ConcurrentHashMap<>();
    //用于存储用户名和当前错误次数
    private static final Map<String,Integer> LOGIN_ERROR_MAP = new ConcurrentHashMap<>();
    /**
     * 退出
     * @param request
     * @return
     */
    @RequestMapping("/logout")
    public AjaxResult logout(HttpServletRequest request){
        HttpSession session =  request.getSession(false);
        session.removeAttribute(ApplicationVariable.SESSION_KEY_USERINFO);
        return AjaxResult.success(1);
    }

    /**
     * 判断用户是否已经登录
     */
    @RequestMapping("/islogin")
    public AjaxResult isLogin(HttpServletRequest request){
        UserInfo userInfo = GetUserSessionTools.getLoginUser(request);
        if (userInfo == null) return AjaxResult.fail(-1, "当前用户未登录");
        return AjaxResult.success(1);
    }


    @RequestMapping("/reg2")
    @Transactional
    public AjaxResult reg2(UserInfo userInfo,HttpServletRequest request){
        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute(ApplicationVariable.SEND_CAPTCHA)==null){
            return AjaxResult.fail(-1,"参数异常");
        }
        Integer code = (int) session.getAttribute(ApplicationVariable.SEND_CAPTCHA);

        //验证码是否失效
        boolean isExpired = !timerTools.getCodeTime().containsKey(code);

        if (isExpired){
            return AjaxResult.fail(-1,"验证码已失效，请重新发送");
        }

        if (userInfo == null ||!StringUtils.hasLength(userInfo.getUsername())||
        !StringUtils.hasLength(userInfo.getPassword())){
            return AjaxResult.fail(-1,"参数异常");
        }


        //获取验证码
        if (!session.getAttribute(ApplicationVariable.SEND_CAPTCHA).equals(userInfo.getCaptcha())){
            return AjaxResult.fail(-1,"验证码错误");
        }

        //用户是否已经存在
        UserInfo resultUsername = userService.selectByUsername(userInfo.getUsername());
        if (resultUsername != null)
            return AjaxResult.fail(-1, "用户已存在!");
        //传入的密码进行加盐加密处理
        userInfo.setPassword(PasswordTools.encrypt(userInfo.getPassword()));

        int result = userService.reg2(userInfo);
        return AjaxResult.success(result);
    }


    //邮箱验证
    @RequestMapping("/email")
    public AjaxResult sendEmail(String email,String username,HttpServletRequest request){
        //进行邮箱处理
        String regex =  "/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*\\.[a-zA-Z0-9]{2,6}$/";

        //生成随机数
        Random random = new Random();
        int SendCaptcha = random.nextInt(10_00000-100000)+100000;

        //邮箱验证
        if (email.matches(regex)){
            return AjaxResult.fail(-1,"邮箱格式正确，请检查邮箱是否填写正确");

        }
            EmailUtil.sendMail(email,username+"你好~"+","+"欢迎使用Sunlight的博客网站，您的验证码为："+SendCaptcha+"请妥善保管，请勿泄露和转发","欢迎注册Sunlight的博客网站");


        //将验证码保存到验证码工具类中进行过期检验
        timerTools.saveCode(SendCaptcha);
        //建立会话保存验证码
        HttpSession session = request.getSession();
        session.setAttribute(ApplicationVariable.SEND_CAPTCHA,SendCaptcha);

        return AjaxResult.success(1);
    }


    //图形验证码
    @RequestMapping("/getcode")
    public  AjaxResult getCode(HttpServletRequest request){
        String[] codeArr = codeTools.createImage();

        HttpSession session = request.getSession();
        session.setAttribute(SESSION_KEY_CHECK_CODE,codeArr[1]);
        return AjaxResult.success("/image/"+codeArr[0]);
    }
    //登录 验证码登录版本

    @RequestMapping("/login")
    public AjaxResult login(String username,String password,String code_input,HttpServletRequest request){


        //检查是否在黑名单中
        if (BLACKLIST_MAP.containsKey(request.getRemoteAddr())){
            long blackTime = BLACKLIST_MAP.get(request.getRemoteAddr());

            //当前时间小于过期时间，还在黑名单中
            if (System.currentTimeMillis()<blackTime){
                return AjaxResult.fail(-1,"多次登录失败导致账号异常，请联系网站管理人员或等待10分钟后重试");

            }else {
                BLACKLIST_MAP.remove(request.getRemoteAddr());//拉出黑名单
            }
        }
        //非空校验
        if (!StringUtils.hasLength(username)||!StringUtils.hasLength(password)){
            return AjaxResult.fail(-1,"参数异常");
        }
        //验证码校验
        if (!code_input.equals(request.getSession(false).getAttribute(SESSION_KEY_CHECK_CODE))){
            return AjaxResult.fail(-1,"验证码错误");
        }

        //密码
        UserInfo userInfo = userService.login(username);
        if (userInfo == null || userInfo.getId()<= 0){
            int errCount = LOGIN_ERROR_MAP.getOrDefault(username,0);
            errCount++;
            LOGIN_ERROR_MAP.put(username,errCount);

            if (errCount == 3){
                //拉入黑名单
                BLACKLIST_MAP.put(request.getRemoteAddr(),System.currentTimeMillis()+ 10 * 60 * 1000);
            }
            return AjaxResult.fail(-1,"输入用户名或密码错误");


        }
        if (!PasswordTools.decrypt(password,userInfo.getPassword())){
            int errCount = LOGIN_ERROR_MAP.getOrDefault(username,0);
            errCount++;
            LOGIN_ERROR_MAP.put(username,errCount);

            if (errCount == 3){
                //拉入黑名单
                BLACKLIST_MAP.put(request.getRemoteAddr(),System.currentTimeMillis()+ 10 * 60 * 1000);
            }
            return AjaxResult.fail(-1,"输入用户名或密码错误");
        }
        //登录成功，清除错误计数
        LOGIN_ERROR_MAP.remove(username);

        HttpSession session = request.getSession(false);
        session.setAttribute(ApplicationVariable.SESSION_KEY_USERINFO,userInfo);
        return AjaxResult.success(1);
    }


    //重置密码
    @RequestMapping("/forgot")
    @Transactional
    public AjaxResult forgot(String username, String password, String email, Integer code_input, HttpServletRequest request) {
        HttpSession session = request.getSession();

        if (session == null || session.getAttribute(ApplicationVariable.SEND_CAPTCHA) == null)
            return AjaxResult.fail(-1, "参数异常");

        // 1. 非空效验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(email)) {
            return AjaxResult.fail(-1, "参数异常");
        }

        //验证码是否失效
        Integer code = (int) session.getAttribute(SEND_CAPTCHA);
        boolean isExpired = !timerTools.getCodeTime().containsKey(code);

        if (isExpired){
            return AjaxResult.fail(-1,"验证码已失效，请重新发送");
        }


        // 2. 验证码校验
        if (!code_input.equals(session.getAttribute(ApplicationVariable.SEND_CAPTCHA))) {
            return AjaxResult.fail(-1, "验证码错误");
        }

        // 3. 根据用户名和邮箱查询用户是否存在
        UserInfo userInfo = userService.selectByUsernameAndEmail(username, email);

        // 5. 根据用户名和邮箱找到指定用户修改新密码
        int result = userService.updatePassword(username, email, PasswordTools.encrypt(password));

        return AjaxResult.success(1);
    }


    @RequestMapping("/upload")
    @Transactional
    public AjaxResult upload(MultipartFile file,HttpServletRequest request){
        UserInfo userInfo = GetUserSessionTools.getLoginUser(request);

        if (userInfo==null){
            return AjaxResult.fail(-1,"参数异常");
        }

        if (file == null || file.isEmpty()){
            return AjaxResult.fail(-1,"文件异常");
        }

        String fileName = UUID.randomUUID()+
                file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));

        File saveFile = new File("root/image/pric/"+fileName);

        try {
            file.transferTo(saveFile);

            String dbFile = "/image/pric/"+fileName;

            int result = userService.filePath(dbFile,userInfo.getId());

            if (result!=1){
                return AjaxResult.fail(-1,"存储图片错误");
            }
            return AjaxResult.success(dbFile);
        }catch (IOException e){
            e.printStackTrace();
        }
        return AjaxResult.fail(-1,"参数异常");

    }



    @RequestMapping("/initpric")
    public AjaxResult initpric(HttpServletRequest request) {
        UserInfo userInfo = GetUserSessionTools.getLoginUser(request);
        if (userInfo == null) return AjaxResult.fail(-1, "当前状态异常");

        UserInfo userInfo1 = userService.getImagePath(userInfo.getId());
        return AjaxResult.success(userInfo1);
    }

}
